package com.mazaiting.mybatisplus.sensitive.plugins;


import com.mazaiting.mybatisplus.encrypt.exception.MybatisCryptoException;
import com.mazaiting.mybatisplus.sensitive.ISensitive;
import com.mazaiting.mybatisplus.sensitive.FiledSensitive;
import com.mazaiting.mybatisplus.sensitive.utils.SensitiveUtil;
import com.mazaiting.mybatisplus.sensitive.provider.SensitiveFieldsProvider;
import com.mazaiting.mybatisplus.sensitive.provider.SensitiveProvider;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Set;

/**
 * 脱敏拦截器
 * @author danghailiang
 */
@Intercepts({
        @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class MybatisSensitivePlugin implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 获取结果集
        Object result = invocation.proceed();
        if (result == null) {
            return null;
        }
        // 是否是ArrayList实现
        if (result instanceof ArrayList resultList) {
            // 是否是空
            if (resultList.isEmpty()) {
                return result;
            }
            // 获取第一个元素
            Object firstItem = resultList.get(0);
            // 判断参数是否符合条件
            boolean needToDecrypt = SensitiveUtil.sensitiveRequired(resultList);
            if (!needToDecrypt) {
                return result;
            }
            // 返回需要被加密属性的set集合
            Set<Field> SensitiveFields = SensitiveFieldsProvider.get(firstItem.getClass());
            if (SensitiveFields == null || SensitiveFields.isEmpty()) {
                return result;
            }
            // 遍历数组
            for (Object item : resultList) {
                SensitiveEntity(SensitiveFields, item);
            }
        } else {
            // 判断
            if (SensitiveUtil.sensitiveRequired(result)) {
                SensitiveEntity(SensitiveFieldsProvider.get(result.getClass()), result);
            }
        }
        return result;
    }

    /**
     *
     * @param SensitiveFields 脱敏的属性
     * @param item 具体值
     * @throws MybatisCryptoException 捕获异常
     */
    private void SensitiveEntity(Set<Field> SensitiveFields, Object item) throws MybatisCryptoException {
        if (SensitiveFields == null ||SensitiveFields.isEmpty()) {
            return;
        }
        // 遍历属性
        for (Field field : SensitiveFields) {
            // 获取改注解的内容
            FiledSensitive filedSensitive = field.getAnnotation(FiledSensitive.class);
            if (filedSensitive != null) {
                try {
                    // 手动获取脱敏处理器
                    Class<? extends ISensitive> globalDefaultSensitive = filedSensitive.sensitive();
                    // 获取要使用的加密处理器，
                    ISensitive sensitive = SensitiveProvider.get(filedSensitive,globalDefaultSensitive);
                    // 暴力反射
                    field.setAccessible(true);
                    // 获取类字节码
                    Object originalVal = field.get(item);
                    if (originalVal != null) {
                        // 解密
                        String sensitiveVal = sensitive.paramSensitive(originalVal.toString());
                        // 从新赋值
                        field.set(item, sensitiveVal);
                    }
                } catch (Exception e) {
                    throw new MybatisCryptoException(e);
                    }
                }
            }
        }


    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }

    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }
}
